package com.ruicar.afs.cloud.basic.task;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.common.service.BasicMainInfoService;
import com.ruicar.afs.cloud.basic.common.service.BasicReceiptRecordService;
import com.ruicar.afs.cloud.basic.common.service.BasicSmsService;
import com.ruicar.afs.cloud.basic.proceeds.debit.entity.BasicDebitBatch;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitBatchService;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitPayBatchService;
import com.ruicar.afs.cloud.basic.proceeds.debit.service.BasicDebitRecordService;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicAutoPaymentConfigService;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.BasicPaymentPoolService;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.common.job.core.biz.model.ReturnT;
import com.ruicar.afs.cloud.common.job.core.handler.annotation.AfsJob;
import com.ruicar.afs.cloud.common.job.core.handler.annotation.AfsJobHandler;
import com.ruicar.afs.cloud.common.modules.contract.enums.BatchStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.DebitModeEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.YesOrNoEnum;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * <p>Description: </p>
 *
 * @author ZC.GUO
 * @version 1.0
 * @date create on 2020-07-09 18:25
 */
@Component
@Slf4j
@AllArgsConstructor
@AfsJob
public class ContractBasicTask {

    private final BasicDebitRecordService basicDebitRecordService;
    private final BasicDebitBatchService basicDebitBatchService;
    private final BasicPaymentPoolService basicPaymentPoolService;
    private final BasicAutoPaymentConfigService basicAutoPaymentConfigService;
    private final BasicMainInfoService basicMainInfoService;
    private final BasicReceiptRecordService basicReceiptRecordService;
    private final AfsBatchInfoService afsBatchInfoService;
    private final BasicSmsService basicSmsService;
    private final BasicDebitPayBatchService basicDebitPayBatchService;

    public Date getBatchDate(){
        return DateUtil.parse(afsBatchInfoService.getSystemBatchInfo("icos").getBatchDate(), DatePattern.PURE_DATE_PATTERN);
    }


    /**
     * 定时生成待扣款数据
     * @author ZC.GUO
     * @param 
     * @return 
     */
    @AfsJobHandler(value = "addDebitRecordList")
    public ReturnT<String> addDebitRecordList(String params){

        log.info("开始执行待扣款数据生成任务");
        basicDebitRecordService.addDebitRecordList(this.getBatchDate());
        log.info("待扣款数据生成任务执行完成");
        return ReturnT.SUCCESS;
    }
    
    /**
     * 定时全量生成扣款批次
     * @author ZC.GUO
     * @param 
     * @return 
     */
    @AfsJobHandler(value = "generateDebitBatch")
    public ReturnT<String> generateDebitBatch(String params) throws ExecutionException, InterruptedException {

        log.info("开始执行扣款批次生成任务");
        basicDebitBatchService.generateDebitBatch(this.getBatchDate());
        log.info("扣款批次生成任务执行完成");
        return ReturnT.SUCCESS;
    }
    
    /**
     * 定时自动发送扣款批次
     * @author ZC.GUO
     * @param 
     * @return 
     */
    @AfsJobHandler(value = "debitBatchSend")
    public ReturnT<String> debitBatchSend(String params) throws ExecutionException, InterruptedException {

        log.info("开始执行发送扣款批次任务");
        List<BatchStatusEnum> batchStatusEnumList = new ArrayList<>();
        batchStatusEnumList.add(BatchStatusEnum.WAIT_SEND);
        batchStatusEnumList.add(BatchStatusEnum.FAIL_SEND);
        List<BasicDebitBatch> debitBatchList = basicDebitBatchService.list(Wrappers.<BasicDebitBatch>query().lambda()
                .in(BasicDebitBatch::getBatchStatus,batchStatusEnumList)
        );
        if (EmptyUtils.isNotEmpty(debitBatchList)){
            for (BasicDebitBatch debitBatch:debitBatchList){
                /**  批次操作之前进行锁定 by ZC.GUO  **/
                debitBatch.setIsOperating(YesOrNoEnum.yes);
                if (basicDebitBatchService.lockOrUnlockBatch(debitBatch)){
                    try{
                        basicDebitBatchService.sendDebitBatch(debitBatch, DebitModeEnum.auto);
                    }catch (Exception e){
                        log.error("批次{}发送失败！",debitBatch.getBatchNo());
                    }finally{
                        /**  无论如何都要解锁 by ZC.GUO  **/
                        debitBatch.setIsOperating(YesOrNoEnum.no);
                        basicDebitBatchService.lockOrUnlockBatch(debitBatch);
                    }
                }
            }
        }
        log.info("发送扣款批次任务执行完成");
        return ReturnT.SUCCESS;
    }
    /**
     * 定时自动查询扣款结果
     * @author ZC.GUO
     * @param
     * @return
     */
    @AfsJobHandler(value = "queryDebitBatchResult")
    public ReturnT<String> queryDebitBatchResult(String params) throws ExecutionException, InterruptedException {

        log.info("开始执行查询扣款结果任务");
        List<BatchStatusEnum> batchStatusEnumList = new ArrayList<>();
        batchStatusEnumList.add(BatchStatusEnum.SUCCESS_SEND);
        batchStatusEnumList.add(BatchStatusEnum.SUCCESS_FEEDBACK);
        batchStatusEnumList.add(BatchStatusEnum.FAIL_FEEDBACK);
        List<BasicDebitBatch> debitBatchList = basicDebitBatchService.list(Wrappers.<BasicDebitBatch>query().lambda()
                .in(BasicDebitBatch::getBatchStatus,batchStatusEnumList)
                .gt(BasicDebitBatch::getGoingCount, BigDecimal.ZERO.intValue())
        );
        if (EmptyUtils.isNotEmpty(debitBatchList)){
            for (BasicDebitBatch debitBatch:debitBatchList){
                /**  批次操作之前进行锁定 by ZC.GUO  **/
                debitBatch.setIsOperating(YesOrNoEnum.yes);
                if (basicDebitBatchService.lockOrUnlockBatch(debitBatch)){
                    try{
                        basicDebitBatchService.queryDebitBatchResult(debitBatch,getBatchDate());
                    }catch (Exception e){
                        log.error("批次{}回盘失败！",debitBatch.getBatchNo());
                    }finally{
                        /**  无论如何都要解锁 by ZC.GUO  **/
                        debitBatch.setIsOperating(YesOrNoEnum.no);
                        basicDebitBatchService.lockOrUnlockBatch(debitBatch);
                    }
                }
            }
        }
        /**  处理提前还款扣款指令 by ZC.GUO  **/
        basicDebitBatchService.scanAndDealPrepaymentDebitOrder();
        log.info("查询扣款结果任务执行完成");
        return ReturnT.SUCCESS;
    }
    /**
     * 自动查询付款结果
     * @author ZC.GUO
     * @param
     * @return
     */
    @AfsJobHandler(value = "queryPayResult")
    public ReturnT<String> queryPayResult(String params) throws ExecutionException, InterruptedException {
        log.info("开始执行自动查询付款结果任务");
        /**  没有结果的msgid by ZC.GUO  **/
        List<String> msgIdList = basicPaymentPoolService.queryMsgIdList();
        if (EmptyUtils.isNotEmpty(msgIdList)){
            for (String msgid : msgIdList){
                basicPaymentPoolService.queryPayResult(msgid);
            }
        }
        log.info("自动查询付款结果任务执行完成");
        return ReturnT.SUCCESS;
    }


    /**
     * 自动付款
     * @author ZC.GUO
     * @param
     * @return
     */
    @AfsJobHandler(value = "payOrderSend")
    public ReturnT<String> payOrderSend(String params) throws ExecutionException, InterruptedException {
        log.info("开始执行自动付款任务");
        basicDebitPayBatchService.autoPay();
        log.info("自动付款任务执行完成");
        return ReturnT.SUCCESS;
    }


    /**
     * 定时发送提前还款数据
     * @author yaorui.zhang
     * @param
     * @return
     */
    @AfsJobHandler(value = "sendRepayMent")
    public ReturnT<String> sendRepayMent(String params) throws ExecutionException, InterruptedException {
        log.info("开始发送提前还款数据");
        basicMainInfoService.sendRepayMent();
        log.info("结束发送提前还款数据");
        return ReturnT.SUCCESS;
    }

    /**
     * 定时发送合同取消数据
     * @author yaorui.zhang
     * @param
     * @return
     */
    @AfsJobHandler(value = "sendContractCancel")
    public ReturnT<String> sendContractCancel(String params) throws ExecutionException, InterruptedException {
        log.info("开始发送合同取消数据");
        basicMainInfoService.sendContractCancel();
        log.info("结束发送合同取消数据");
        return ReturnT.SUCCESS;
    }

    /**
     * 定时发送合同关闭数据
     * @param
     * @return
     */
    @AfsJobHandler(value = "sendcontractClose")
    public ReturnT<String> sendcontractClose(String params) throws ExecutionException, InterruptedException{
        log.info("开始发送合同关闭数据");
        basicReceiptRecordService.sendcontractClose();
        log.info("结束发送合同关闭数据");
        return ReturnT.SUCCESS;
    }
    /**
     * 定时发送短信
     * @param
     * @return
     */
    @AfsJobHandler(value = "sendMessage")
    public ReturnT<String> sendMessage(String params) throws ExecutionException, InterruptedException{
        log.info("开始发送发送短信");
        basicSmsService.sendMessage();
        log.info("结束发送发送短信");
        return ReturnT.SUCCESS;
    }
}
